package com.yihen.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yihen.bean.Weight;
import com.yihen.dto.Result;
import com.yihen.dto.WeightDTO;
import com.yihen.mapper.WeightMapper;
import com.yihen.service.WeightService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Date;
import java.time.LocalDate;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class WeightServiceImpl implements WeightService {
    @Autowired
    private WeightMapper weightMapper;


    @Override
    public Result addWeight(Weight weight) {
        Weight record = checkWeightRecordExist(weight.getUserId(), weight.getDate());

        // 记录不存在,则添加
        if (Objects.isNull(record)) {
            log.debug("记录不存在,添加记录:{}",weight);
            weightMapper.insert(weight);
        } else {         // 记录存在,则更新
            log.debug("记录存在,更新记录:{}",weight);
            weightMapper.update(weight,
                    new QueryWrapper<Weight>()
                            .eq("user_id", weight.getUserId())
                            .eq("date", weight.getDate())
            );
        }

        // 异步更新其他值
        updateOtherValue(weight);

        return Result.ok("添加成功",null);
    }

    @Override
    public Result getWeightByDate(Long userId, String startDate, String endDate) {
        QueryWrapper<Weight> wrapper = new QueryWrapper<>();
        wrapper.between("date",startDate,endDate).eq("user_id",userId);
        List<Weight> weights = weightMapper.selectList(wrapper);
        // 包装体重
        WeightDTO weightDTO = getWeightDTO(weights);
        return Result.ok("",weightDTO);
    }


    // 包装体重
    private WeightDTO getWeightDTO(List<Weight> weights) {
        // 根据日期先后排序weights
        weights.sort((o1, o2) -> {
            Date date1 = Date.valueOf(o1.getDate());
            Date date2 = Date.valueOf(o2.getDate());
            return date1.compareTo(date2);
        });
        WeightDTO weightDTO = new WeightDTO();
        weightDTO.setDates(weights.stream().map(Weight::getDate).toList());


        weightDTO.setMorningWeights(weights.stream().map(Weight::getMorningWeight).toList());
        weightDTO.setEveningWeights(weights.stream().map(Weight::getEveningWeight).toList());
        weightDTO.setAvgWeights(weights.stream().map(Weight::getAvgWeight).toList());
        weightDTO.setDiffWeights(weights.stream().map(Weight::getDiffWeight).toList());

        // 合并 morningWeights 和 eveningWeights
        List<Float> allWeights = Stream.concat(
                weights.stream().map(Weight::getMorningWeight).filter(Objects::nonNull),
                weights.stream().map(Weight::getEveningWeight).filter(Objects::nonNull)
        ).collect(Collectors.toList());

        weightDTO.setMaxWeight(allWeights.stream().max(Float::compareTo).orElse(0.0f));
        weightDTO.setMinWeight(allWeights.stream().min(Float::compareTo).orElse(0.0f));

        weightDTO.setIntervalWeight(weightDTO.getMaxWeight() != null && weightDTO.getMinWeight() != null
                ? (weightDTO.getMaxWeight() - weightDTO.getMinWeight()) / 10
                : null);

        return weightDTO;
    }


    // 判断当天体重记录是否存在
    private Weight checkWeightRecordExist(Long userId, String date) {
        // 1. 解析日期
        LocalDate parse = LocalDate.parse(date);
        // 2. 查询该用户当前日期是否存在记录
        QueryWrapper<Weight> weightQueryWrapper = new QueryWrapper<>();
        weightQueryWrapper.eq("user_id", userId)
                .eq("date", parse);
        Weight weight = weightMapper.selectOne(weightQueryWrapper);
        return weight;
    }

    private void updateOtherValue(Weight weight) {


        CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
            log.debug("异步更新其他值");
            // 1. 获取该用户当前日期记录
            QueryWrapper<Weight> weightQueryWrapper = new QueryWrapper<>();
            weightQueryWrapper.eq("user_id", weight.getUserId())
                    .eq("date", weight.getDate());
            Weight weight_update = weightMapper.selectOne(weightQueryWrapper);
            // 2. 当早上和晚上体重值全部存在时,开始计算其他值
            if (weight_update.getEveningWeight() != 0 && weight_update.getMorningWeight() != 0) {
                // 2.1 计算平均值
                weight_update.setAvgWeight((weight_update.getEveningWeight() + weight_update.getMorningWeight()) / 2);
                // 2.2 计算差值,取绝对值
                weight_update.setDiffWeight(Math.abs(weight_update.getEveningWeight() - weight_update.getMorningWeight()));
                // 2.3 更新记录
                weightMapper.update(weight_update,
                        new QueryWrapper<Weight>()
                                .eq("id", weight_update.getId())
                );
            }

        });


    }
}
